package com.hzhc.controller.sysmanage;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hzhc.annotation.SysTemLog;
import com.hzhc.common.BaseController;
import com.hzhc.constant.ScheduleConstants;
import com.hzhc.dto.UserDto;
import com.hzhc.entity.TaskPlan;
import com.hzhc.enumBean.ResultUtilCodeEnum;
import com.hzhc.service.TaskPlanService;
import com.hzhc.util.quarz.ScheduleUtils;
import com.hzhc.utils.ResultUtil;
import com.hzhc.utils.TokenUtil;
import com.hzhc.vo.TaskPlanVo;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.formula.functions.T;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * <p>
 * 任务管理 前端控制器
 * </p>
 *
 * @author 功不唐捐
 * @since 2024-04-07
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/taskManage")
public class TaskPlanController extends BaseController {

    private final TaskPlanService taskPlanService;
    private final Scheduler scheduler;

    /**
     * 项目启动时，初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理（注：不能手动修改数据库ID和任务组名，否则会导致脏数据）
     */
    @PostConstruct
    public void init() {
        try {
            scheduler.clear();
            List<TaskPlan> jobList = taskPlanService.list();
            for (TaskPlan job : jobList) {
                ScheduleUtils.createScheduleJob(scheduler, job);
            }
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     ** 获取定时任务管理列表
     * @param vo
     * @return
     */
    @RequestMapping("/getTaskPlanVoList")
    public ResultUtil<List<TaskPlanVo>> getTaskPlanVoList(@RequestBody TaskPlanVo vo) {
        Page<TaskPlanVo> page =new Page<>(vo.getPageIndex(), vo.getPageSize());
        List<TaskPlanVo> taskPlanVoList = taskPlanService.getTaskPlanVoList(page, vo);
        return ResultUtil.build(taskPlanVoList,page.getTotal(), page.getPages(), ResultUtilCodeEnum.SUCCESS);
    }

    /**
     * 检测定时任务管理名称
     * @param data
     * @return
     */
    @PostMapping("/checkTaskPlanNo")
    public ResultUtil<T> checkTaskPlanNo(@RequestBody JSONObject data) {
        Long id = null;
        String planName = data.getString("planName");
        if (data.containsKey("id")) {
            id = data.getLong("id");
        }
        Boolean bool = taskPlanService.checkTaskPlanByField("plan_name", planName, id);
        if (bool) {
            return ResultUtil.build(ResultUtilCodeEnum.TASKPLANNAME_ALREAD_EXIST);
        }
        return ResultUtil.ok();
    }

    /**
     * 检测定时任务管理执行周期
     * @param data
     * @return
     */
    @PostMapping("/checkExecuteCycle")
    public ResultUtil<T> checkExecuteCycle(@RequestBody JSONObject data) {
        String executeCycle = data.getString("executeCycle");
        Boolean b = taskPlanService.checkCronExpressionIsValid(executeCycle);
        if (!b) {
            return ResultUtil.build(ResultUtilCodeEnum.EXECUTECYCLE_INCORRECT_FORMAT);
        }
        return ResultUtil.ok();
    }

    /**
     * 定时任务管理新增
     * @param request
     * @param taskPlan
     * @return
     */
    @PostMapping("/addTaskPlan")
    @SysTemLog(operModul = "定时任务管理管理-定时任务管理新增", operType = "新增", operDesc = "定时任务管理管理新增功能", modular="PC")
    public ResultUtil<T> addTaskPlan(HttpServletRequest request, @RequestBody TaskPlan taskPlan){
        Boolean bool = taskPlanService.checkTaskPlanByField("plan_name", taskPlan.getPlanName(), null);
        if (bool) {
            return ResultUtil.build(ResultUtilCodeEnum.TASKPLANNAME_ALREAD_EXIST);
        }
        bool = taskPlanService.checkCronExpressionIsValid(taskPlan.getExecuteCycle());
        if (!bool) {
            return ResultUtil.build(ResultUtilCodeEnum.EXECUTECYCLE_INCORRECT_FORMAT);
        }
        UserDto user = TokenUtil.getUser(request);
        taskPlan.setUserId(user.getId());
        Boolean b = taskPlanService.addTaskPlan(taskPlan);
        if(b){
            ScheduleUtils.createScheduleJob(scheduler, taskPlan);
            return ResultUtil.ok();
        }else{
            return ResultUtil.fail();
        }
    }

    /**
     * 定时任务管理修改
     * @param request
     * @param taskPlan
     * @return
     */
    @PostMapping("/updateTaskPlan")
    @SysTemLog(operModul = "定时任务管理管理-定时任务管理修改", operType = "修改", operDesc = "定时任务管理管理修改功能", modular="PC")
    public ResultUtil<T> updateTaskPlan(HttpServletRequest request, @RequestBody TaskPlan taskPlan) {
        Boolean bool = taskPlanService.checkTaskPlanByField("plan_name", taskPlan.getPlanName(), taskPlan.getId());
        if (bool) {
            return ResultUtil.build(ResultUtilCodeEnum.TASKPLANNAME_ALREAD_EXIST);
        }
        bool = taskPlanService.checkCronExpressionIsValid(taskPlan.getExecuteCycle());
        if (!bool) {
            return ResultUtil.build(ResultUtilCodeEnum.EXECUTECYCLE_INCORRECT_FORMAT);
        }
        UserDto user = TokenUtil.getUser(request);
        taskPlan.setUpdateUserId(user.getId());
        Boolean b =  taskPlanService.updateTaskPlan(taskPlan);
        if(b){
            updateSchedulerJob(taskPlan, ScheduleConstants.DEFAULT);
            return ResultUtil.ok();
        }else{
            return ResultUtil.fail();
        }
    }

    /**
     * 定时任务管理删除
     * @param id
     * @return
     */
    @PostMapping("/delTaskPlan/{id}")
    @SysTemLog(operModul = "定时任务管理管理-定时任务管理删除", operType = "删除", operDesc = "定时任务管理管理删除功能", modular="PC")
    public ResultUtil<T> delTaskPlan(@PathVariable("id")Integer id) {
        Boolean b = taskPlanService.delTaskPlan(id);
        if(b){
            try {
                //删除定时任务
                scheduler.deleteJob(ScheduleUtils.getJobKey(Long.valueOf(id), ScheduleConstants.DEFAULT));
            } catch (SchedulerException e) {
                throw new RuntimeException(e);
            }
            return ResultUtil.ok();
        }else{
            return ResultUtil.fail();
        }
    }

    /**
     * 定时任务管理启动/结束
     * @return
     */
    @PostMapping("/updateTaskPlanStatus")
    @SysTemLog(operModul = "定时任务管理管理-定时任务管理启动结束", operType = "修改", operDesc = "定时任务管理管理启动结束功能", modular="PC")
    public ResultUtil<T> updateTaskPlanStatus(@RequestBody TaskPlan taskPlan) {
        Boolean b = taskPlanService.updateTaskPlanStatus(taskPlan);
        if(b){
            try {
                if (ScheduleConstants.Status.NORMAL.getValue().equals(taskPlan.getStatus())) {
                    //恢复任务
                    scheduler.resumeJob(ScheduleUtils.getJobKey(taskPlan.getId(), ScheduleConstants.DEFAULT));
                } else if (ScheduleConstants.Status.PAUSE.getValue().equals(taskPlan.getStatus())){
                    //暂停任务
                    scheduler.pauseJob(ScheduleUtils.getJobKey(taskPlan.getId(), ScheduleConstants.DEFAULT));
                }
            } catch (SchedulerException e) {
                throw new RuntimeException(e);
            }
            return ResultUtil.ok();
        }else {
            return ResultUtil.fail();
        }
    }

    /**
     * 更新任务
     *
     * @param job 任务对象
     * @param jobGroup 任务组名
     */
    public void updateSchedulerJob(TaskPlan job, String jobGroup) {
        Long jobId = job.getId();
        job = taskPlanService.getById(jobId);
        if(StrUtil.isBlank(job.getInvokeTarget())){
            throw new RuntimeException("执行目标方法不能为空");
        }
        // 判断是否存在
        JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
        try {
            if (scheduler.checkExists(jobKey)) {
                // 防止创建时存在数据问题 先移除，然后在执行创建操作
                scheduler.deleteJob(jobKey);
                ScheduleUtils.createScheduleJob(scheduler, job);
            }
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }
}
